"""
    Author:
    Date: 2018-11-08

    充值管理类
"""

import random
from django.conf import settings

from apps.gma import helpers as gma_helpers
from entities import guild_mgr
from entities import user_mgr
from entities import vchat_api_mgr
from entities.consts import *
from utils import alipay_util
from utils import db
from utils import util
from utils import wx_config
from utils.log import Log
from utils.wx_util import WechatApi


def fetch_weixin_mch_id_for_mp(uid):
    """ 获取微信公众号充值应使用的商户号 """
    mch_ids = wx_config.WX_MCH_IDS_FOR_MP
    if not mch_ids:
        return None

    # 用户交替使用商户号, 假设有A，B，C三个账号，则第一次充值使用A，第二次使用B，第三次使用C
    pay_count = get_total_try_recharge_count(uid)
    index = (int(uid) + pay_count) % len(mch_ids)
    mch_id = mch_ids[index]
    return mch_id

    # # 随机选择一个商户号
    # random.seed()
    # return random.choice(mch_ids)


def fetch_weixin_mch_id_for_h5(uid):
    """ 获取微信H5页面充值应使用的商户号

    用户交替使用商户号, 假设有A，B，C三个账号，则第一次充值使用A，第二次使用B，第三次使用C
    """
    pay_count = get_total_recharge_count(uid)
    mch_ids = wx_config.WX_MCH_IDS_FOR_H5
    if not mch_ids:
        return None

    index = pay_count % len(mch_ids)
    mch_id = mch_ids[index]
    return mch_id


def get_diamond_stat_detail():
    """ 获取钻石数据详情 """
    today_begin_time, today_end_time = util.get_today_interval()

    # 累计充值钻石数
    total_charged_diamond = user_mgr.get_charged_diamond('', today_end_time)
    # 测试人员充值金额
    total_test_charged_diamond = user_mgr.get_test_charged_diamond('', today_end_time)
    # 用户分享赠送的钻石
    agent_share_diamond = user_mgr.get_user_consumption_amount('', today_end_time, 6)
    # 用户接收邀请赠送的钻石
    invited_by_agent_diamond = user_mgr.get_user_consumption_amount('', today_end_time, 7)
    # 合伙人分享赠送的钻石
    invited_by_partner_diamond = user_mgr.get_user_consumption_amount('', today_end_time, 8)
    # 新人免费赠送的钻石
    activity_free_diamond = user_mgr.get_user_consumption_amount('', today_end_time, 9)
    # GM赠送的钻石
    gm_diamond = user_mgr.get_user_consumption_amount('', today_end_time, 98)
    # 购买vip的钻石
    vip_diamond = user_mgr.get_user_consumption_amount('', today_end_time, 106)
    # 实际剩余钻石总量
    total_left_diamond = user_mgr.get_total_diamond_amount()
    # 累计钻石产出
    total_diamond_input = total_charged_diamond + total_test_charged_diamond + agent_share_diamond + invited_by_agent_diamond + invited_by_partner_diamond + activity_free_diamond + gm_diamond
    # 累计钻石消耗
    total_diamond_output = vip_diamond

    # 公会结算的趣票
    guild_archive_ticket = guild_mgr.get_guild_archive_ticket('', today_end_time)
    # 个人结算的趣票
    caster_archive_ticket = 502 + 1064 - 5 + 90 + 98

    # devkeep购买短视频的趣票
    devkeep_ticket_for_video = user_mgr.get_user_consumption_amount('', today_end_time, DEVKEEP_TICKET_INPUT_SELL_VIDEO)
    # devkeep视频通话的趣票
    devkeep_ticket_for_call = user_mgr.get_user_consumption_amount('', today_end_time, DEVKEEP_TICKET_INPUT_VIDEO_CHAT)
    # devkeep视频通话的趣票
    devkeep_ticket_for_gift = user_mgr.get_user_consumption_amount('', today_end_time, DEVKEEP_TICKET_INPUT_RECEIVE_GIFT)
    # devkeep累计的趣票
    devkeep_tickets = devkeep_ticket_for_video + devkeep_ticket_for_call + devkeep_ticket_for_gift

    # 实际剩余聊票总量
    total_left_ticket = user_mgr.get_total_ticket_amount()
    # 累计聊票产出
    total_ticket_input = guild_archive_ticket + caster_archive_ticket + total_left_ticket

    # 预测的钻石剩余量
    predicted_left_diamond_amount = total_diamond_input - total_ticket_input + devkeep_tickets
    # 钻石的预测偏差
    diamond_delta = predicted_left_diamond_amount - total_left_diamond + total_diamond_output

    context = {
        # 累计充值钻石数
        'total_charged_diamond': total_charged_diamond,
        # 累计测试充值钻石数
        'total_test_charged_diamond': total_test_charged_diamond,
        # 用户分享赠送的钻石
        'agent_share_diamond': agent_share_diamond,
        # 用户接收邀请赠送的钻石
        'invited_by_agent_diamond': invited_by_agent_diamond,
        # 合伙人分享赠送的钻石
        'invited_by_partner_diamond': invited_by_partner_diamond,
        # 新人免费赠送的钻石
        'activity_free_diamond': activity_free_diamond,
        # GM赠送的钻石
        'gm_diamond': gm_diamond,
        # 累计钻石产出
        'total_diamond_input': total_diamond_input,
        # 实际剩余钻石总量
        'total_left_diamond': total_left_diamond,


        # devkeep购买短视频的趣票
        'devkeep_ticket_for_video': devkeep_ticket_for_video,
        # devkeep视频通话的趣票
        'devkeep_ticket_for_call': devkeep_ticket_for_call,
        # devkeep视频通话的趣票
        'devkeep_ticket_for_gift': devkeep_ticket_for_gift,
        # devkeep累计贡献的趣票
        'devkeep_tickets': devkeep_tickets,

        # 公会结算的趣票
        'guild_archive_ticket': guild_archive_ticket,
        # 个人结算的趣票
        'caster_archive_ticket': caster_archive_ticket,
        # 实际剩余聊票总量
        'total_left_ticket': total_left_ticket,
        # 累计聊票产出
        'total_ticket_input': total_ticket_input,

        # 预测剩余钻石数
        'predicted_left_diamond_amount': predicted_left_diamond_amount,
        # 钻石误差数
        'diamond_delta': diamond_delta,
    }
    return context


def create_prepay_record(uid, rmb, openid):
    """ 创建预支付记录 """
    # 分配商户号
    mch_id = fetch_weixin_mch_id_for_mp(uid)
    if mch_id is None:
        Log.error(f'创建微信公众号充值预支付记录失败, 未找到可用的商户号: uid={uid}, rmb={rmb}, openid={openid}')
        return None

    # # 测试充值
    # if uid == 10848705:
    #     mch_id = '1565589951'

    # 向ApiServer请求out_trade_no
    data = vchat_api_mgr.create_wx_pay_order(uid, rmb, mch_id)
    if data is None:
        return None

    out_trade_no = data.get('out_trade_no', None)
    if out_trade_no is None:
        Log.error('Fetch out_trade_no from api-server failed!')
        return None
    Log.info(f'Fetch out_trade_no from api-server: {out_trade_no}')

    params = WechatApi.get_choose_wx_pay_params(uid, openid, rmb, out_trade_no, mch_id)
    return params


def pay_with_weixin_h5(uid, rmb, client_ip, wap_name):
    """ 在h5页面使用微信支付 """
    # 分配商户号
    mch_id = fetch_weixin_mch_id_for_h5(uid)
    if mch_id is None:
        Log.error(f'创建微信H5充值预支付记录失败, 未找到可用的商户号: uid={uid}, rmb={rmb}, ip={client_ip}, wap={wap_name}')
        return None

    # 向ApiServer请求out_trade_no
    data = vchat_api_mgr.create_wx_pay_order(uid, rmb, mch_id)
    out_trade_no = data.get('out_trade_no', None) if data else None
    if out_trade_no is None:
        Log.error('Fetch out_trade_no from api-server failed!')
        return None
    Log.info(f'Fetch out_trade_no from api-server: {out_trade_no}')

    params = WechatApi.get_wx_pay_for_h5_params(uid, rmb, out_trade_no, client_ip, wap_name, mch_id)
    return params


def pay_with_ali_h5(uid, rmb):
    """ 在h5页面使用支付宝支付 """
    # 向ApiServer请求out_trade_no
    data = vchat_api_mgr.create_api_wap_pay_order(uid, rmb)
    out_trade_no = data.get('out_trade_no', None) if data else None
    if out_trade_no is None:
        Log.error('Fetch out_trade_no from api-server failed!')
        return None
    Log.info(f'Fetch out_trade_no from api-server: {out_trade_no}')

    # 处理测试账号的充值金额
    if uid in settings.TEST_UIDS_FOR_PAY:
        rmb = 0.01

    response = alipay_util.pay_on_web_page(uid, rmb, out_trade_no, rmb)
    return response


def get_recharge_list(count):
    """ 获取充值列表 """
    sql = f'''
        SELECT      c.*,
                    u.avatar,
                    u.nickname
        FROM        cmf_users_charge as c
        JOIN        cmf_users AS u ON c.touid=u.id
        WHERE       status=1
        ORDER BY    id DESC
        LIMIT       {count};
    '''
    data = db.query_data_from_db(sql)
    return [] if data is None else data


def get_recharge_list_by_time(begin_time, end_time, request=None):
    """ 获取指定时间范围内的充值列表 """
    apps_condition = gma_helpers.build_app_filter_condition_for_request(request)
    sql = f'''
        SELECT      c.*,
                    u.avatar,
                    u.nickname
        FROM        cmf_users_charge as c
        JOIN        cmf_users AS u ON c.touid=u.id
        WHERE       {apps_condition} AND status=1 AND
                    add_time>=%(begin_time)s AND
                    add_time<=%(end_time)s
        ORDER BY    id DESC
        LIMIT       1000;
    '''
    params = {
        'begin_time': begin_time,
        'end_time': end_time,
    }
    data = db.query_data_from_db(sql, params)
    return [] if data is None else data


def get_total_recharge_amount():
    """ 获取用户的累计充值人民币 """
    sql = f'''
        SELECT      IFNULL(SUM(money), 0)   AS total_amount
        FROM        cmf_users_charge        AS c
        WHERE       c.status=1;
    '''
    data = db.query_data_from_db(sql)
    return data[0]['total_amount'] if data else 0


def get_income_amount_with_type(type, begin_time, end_time):
    """ 获取用户在指定时间内指定类型的收益 """
    sql = '''
        SELECT      IFNULL(SUM(amount), 0) AS total_amount
        FROM        cmf_users_consumption_log
        WHERE       type=%(type)s AND
                    add_time>=%(begin_time)s AND
                    add_time<=%(end_time)s;
    '''
    params = {
        'type': str(type),
        'begin_time': begin_time,
        'end_time': end_time,
    }
    data = db.query_data_from_db(sql, params)
    return data[0]['total_amount'] if data else 0


def get_charge_count_for_money(uid, money):
    """ 获取用户充值指定金额的次数 """
    sql = f'''
        SELECT      COUNT(c.*) AS count
        FROM        cmf_users_charge AS c
        WHERE       c.touid={uid} AND
                    c.money={money} AND
                    c.status=1;
    '''
    data = db.query_data_from_db(sql)
    return data[0]['count'] if data else 0


def get_daily_pay_amount(day, request=None):
    """ 获取每日的充值统计数据 """
    apps_condition = gma_helpers.build_app_filter_condition_for_request(request)
    sql = f'''
        SELECT      DATE_FORMAT(add_time, '%Y-%m-%d') AS d,
                    COUNT(*) as total_count,
                    SUM(money) AS total_amount
        FROM        cmf_users_charge AS c
        JOIN        cmf_users AS u ON u.id=c.uid
        WHERE       {apps_condition} AND
                    c.status=1 AND
                    u.is_test_account=0 AND
                    c.comment!='苹果测试账号'
        GROUP BY    d
        ORDER BY    d DESC
        LIMIT       {day};
    '''
    data = db.query_data_from_db(sql)
    return data if data else []


def get_total_try_recharge_count(uid):
    """ 获取用户的累计充值次数 """
    sql = f'''
        SELECT      COUNT(*) AS total_count
        FROM        cmf_users_charge AS c
        WHERE       c.uid={uid};
    '''
    data = db.query_data_from_db(sql)
    return data[0]['total_count'] if data else 0


def get_total_recharge_count(uid):
    """ 获取用户的累计充值次数 """
    sql = f'''
        SELECT      COUNT(*) AS total_count
        FROM        cmf_users_charge AS c
        WHERE       c.status=1;
    '''
    data = db.query_data_from_db(sql)
    return data[0]['total_count'] if data else 0


def create_test_pay_record(uid, money, pay_type, wx_mch_id=''):
    """ 创建测试充值记录 """
    sql = '''
        INSERT INTO cmf_users_charge
        SET         uid=%(uid)s,
                    touid=%(uid)s,
                    money=%(money)s,
                    wx_mch_id="%(wx_mch_id)s",
                    type=%(pay_type)s,
                    status=1;
    '''
    params = {
        'uid': str(uid),
        'money': str(money),
        'pay_type': str(pay_type),
        'wx_mch_id': wx_mch_id,
    }
    affected_rows = db.execute_sql(sql, params)
    return affected_rows == 1


def get_total_recharge_count_in_platform(uid, platform):
    """ 获取用户在指定平台的累计充值次数 """
    sql = f'''
        SELECT      COUNT(*) AS total_count
        FROM        cmf_users_charge AS c
        WHERE       c.status=1 AND
                    c.touid={uid} AND
                    c.type={platform};
    '''
    data = db.query_data_from_db(sql)
    return data[0]['total_count'] if data else 0


if __name__ == '__main__':
    print('ok')
